#ifndef SERVER_H
#define SERVER_H
#include <QTcpServer>
#include <QTcpSocket>
#include <QVector>
#include <QDataStream>
#include "isi.h"
#include <QTimer>


/**
@startuml
title Алгоритм работы сервера часть 1
start
: Старт сервера;
if (Запустился?) then (Нет)
    #pink: Ошибка;
    end;
else (Да)
    repeat:Сервер слушает;
    repeat while(Подключился клиент?) is(Нет) not(Да)
        if(Назначен descriptor
        сокету клиента) then(Нет)
            #pink:Вывести ошибку;
            end;
        else(Да)
            :Настроить сведения о клиенте;
            :Запуск таймера;
            :Часть 2;
            detach;
@enduml
 */
/**
@startuml
title Алгоритм работы сервера часть 2
:Часть 1;
:Настроить сведения о клиенте;
:Запуск таймера;
repeat:Сработал timerEvent();
        :Собрать следующее сообщение
        для клиента;
        if(Сообщение пустое?) then (Да)
        :Остановить таймер;
        stop;
    else (Нет)
        repeat :Отправить сообщение клиенту;
        :Ждать подтверждения от клиента;
        backward : 3 раза;
        repeat while(Ответ пришёл?) is(Нет) not(Да)
            :Выйти из метода sendToClient();
    endif;

@enduml
 */

/**
 * @brief The Server class          класс сервера
 * @details                         передаёт клиенту кадры данных.
 *                                  кадр состоит из информационного сообщения с именем файла, который имеет вид: "file:<имя_файла.isi> <кол-во_записей_в_файле_isi";
 *                                  сообщения с данными из таблицы header:  "header:<поля_из_таблицы_header>"
 *                                  и сообщения с данными из таблицы data (все записи): "data:<поля_из_таблицы_data>"
 *
 */

class Server : public QTcpServer
{
    Q_OBJECT

public:
    Server();

    /**
     * @brief The infoClient struct         структура сведения о клиенте
     */
     typedef struct {
        QTcpSocket *socket;                 ///< сокет клиента
        Isi* isi;                           ///< файл *.isi
        quint16 hZ = 10;                    ///< частота выдачи одного сообщения, Гц, 1 Гц = 1 раз в сек.
        int rowSend = -1;                   ///< последняя переданное сообщение (запись таблицы data файла isi)
        int timerId;                        ///< таймер для передачи сообщения
    }InfoClient;

    /**
         * @brief sendToClient              передать данные клиенту
         * @param str                       строка (данные)
         */
    bool sendToClientTypeData(InfoClient &client);
    /**
     * @brief getMessage                    получить и сформировать сообщение из данных isi
     * @param row                           номер строки из БД
     * @return                              вернет сформированное сообщение
     */
    QString getMessage(int &row, Isi *isi, InfoClient &client);
    /**
     * @brief shetchik                      счётчик для повторной отправки сообщения
     * @param zero                          флаг нужно ли обнулять счётчик: 0 - да, 1 - нет
     * @return                              значение счётчика
     */
    int shetchik(int zero = 1);
    /**
     * @brief sendToClientTypeFile          передать клиенту данные с типом файла
     * @param client                        клиент для получения
     * @return
     */
    bool sendToClientTypeFile(InfoClient &client);
    /**
     * @brief sendToClientTypeHeader        передать клиенту данные из header
     * @param client                        клиент для получения
     * @return
     */
    bool sendToClientTypeHeader(InfoClient &client);
    /**
     * @brief sendToClientInfMsg            передать клиенту информационное сообщение
     * @param client                        клиент для получения
     * @return
     */
    bool sendToClientInfMsg(InfoClient &client);

public slots:
    /**
     * @brief incomingConnection            слот обработки нового подключения
     * @param socketDescriptor              опознавательный номер клиента
     */
    void incomingConnection(qintptr socketDescriptor);
    /**
     * @brief slotReadyRead                 слот обработки целостности полученных данных
     */
    void slotReadyRead();
    /**
     * @brief slotDeleteSocket              слот для удаления сокета из вектора
     */
    void slotDeleteSocket();
    /**
     * @brief setPath                       назначить клиету файл с данными для передачи
     * @param num_client                    количество подключенных клиентов
     * @param isiRead                       структура с данными о клиенте
     */
    void setPath(int num_client, InfoClient &isiRead);

protected:
    /**
     * @brief timerEvent                    событие связанные с таймером
     */
    virtual void timerEvent( QTimerEvent * );

private:
    /**
     * @brief d_numClients                  количество клиентов
     */
    int d_numClients;

    /**
     * @brief d_clients                     вектор из структур с данными о клиентах
     */
    QVector<InfoClient> d_clients;
    /**
     * @brief d_sockets                     вектор сокетов подключенных клиентов
     */
    QVector <QTcpSocket*> d_sockets;
    /**
     * @brief d_nextBlockSize               размер следующего блока
     */
    quint16 d_nextBlockSize;
};
#endif // SERVER_H
